// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*!
 * @file CompleteTypeObject.cpp
 * This source file contains the definition of the described types in the IDL file.
 *
 * This file was generated by the tool fastddsgen.
 */

#ifdef _WIN32
// Remove linker warning LNK4221 on Visual Studio
namespace {
char dummy;
} // namespace
#endif // ifdef _WIN32

#include "Complete.h"
#include "CompleteTypeObject.h"
#include <mutex>
#include <utility>
#include <sstream>
#include <fastdds/rtps/common/CdrSerialization.hpp>
#include <fastrtps/rtps/common/SerializedPayload.h>
#include <fastrtps/utils/md5.h>
#include <fastrtps/types/TypeObjectFactory.h>
#include <fastrtps/types/TypeNamesGenerator.h>
#include <fastrtps/types/AnnotationParameterValue.h>

using namespace eprosima::fastrtps::rtps;

void registerCompleteTypes()
{
    static std::once_flag once_flag;
    std::call_once(once_flag, []()
            {
                TypeObjectFactory* factory = TypeObjectFactory::get_instance();
                factory->add_type_object("Timestamp", GetTimestampIdentifier(true),
                GetTimestampObject(true));
                factory->add_type_object("Timestamp", GetTimestampIdentifier(false),
                GetTimestampObject(false));


                factory->add_type_object("Point", GetPointIdentifier(true),
                GetPointObject(true));
                factory->add_type_object("Point", GetPointIdentifier(false),
                GetPointObject(false));


                factory->add_type_object("MessageDescriptor", GetMessageDescriptorIdentifier(true),
                GetMessageDescriptorObject(true));
                factory->add_type_object("MessageDescriptor", GetMessageDescriptorIdentifier(false),
                GetMessageDescriptorObject(false));


                factory->add_type_object("Message", GetMessageIdentifier(true),
                GetMessageObject(true));
                factory->add_type_object("Message", GetMessageIdentifier(false),
                GetMessageObject(false));


                factory->add_type_object("CompleteData", GetCompleteDataIdentifier(true),
                GetCompleteDataObject(true));
                factory->add_type_object("CompleteData", GetCompleteDataIdentifier(false),
                GetCompleteDataObject(false));

            });
}

const TypeIdentifier* GetTimestampIdentifier(
        bool complete)
{
    const TypeIdentifier* c_identifier = TypeObjectFactory::get_instance()->get_type_identifier("Timestamp", complete);
    if (c_identifier != nullptr && (!complete || c_identifier->_d() == EK_COMPLETE))
    {
        return c_identifier;
    }

    GetTimestampObject(complete); // Generated inside
    return TypeObjectFactory::get_instance()->get_type_identifier("Timestamp", complete);
}

const TypeObject* GetTimestampObject(
        bool complete)
{
    const TypeObject* c_type_object = TypeObjectFactory::get_instance()->get_type_object("Timestamp", complete);
    if (c_type_object != nullptr)
    {
        return c_type_object;
    }
    else if (complete)
    {
        return GetCompleteTimestampObject();
    }
    //else
    return GetMinimalTimestampObject();
}

const TypeObject* GetMinimalTimestampObject()
{
    const TypeObject* c_type_object = TypeObjectFactory::get_instance()->get_type_object("Timestamp", false);
    if (c_type_object != nullptr)
    {
        return c_type_object;
    }

    TypeObject* type_object = new TypeObject();
    type_object->_d(EK_MINIMAL);
    type_object->minimal()._d(TK_STRUCTURE);

    type_object->minimal().struct_type().struct_flags().IS_FINAL(false);
    type_object->minimal().struct_type().struct_flags().IS_APPENDABLE(false);
    type_object->minimal().struct_type().struct_flags().IS_MUTABLE(false);
    type_object->minimal().struct_type().struct_flags().IS_NESTED(false);
    type_object->minimal().struct_type().struct_flags().IS_AUTOID_HASH(false); // Unsupported

    MemberId memberId = 0;
    MinimalStructMember mst_seconds;
    mst_seconds.common().member_id(memberId++);
    mst_seconds.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    mst_seconds.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    mst_seconds.common().member_flags().IS_EXTERNAL(false); // Unsupported
    mst_seconds.common().member_flags().IS_OPTIONAL(false);
    mst_seconds.common().member_flags().IS_MUST_UNDERSTAND(false);
    mst_seconds.common().member_flags().IS_KEY(false);
    mst_seconds.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    mst_seconds.common().member_type_id(*TypeObjectFactory::get_instance()->get_type_identifier("int32_t", false));


    MD5 seconds_hash("seconds");
    for (int i = 0; i < 4; ++i)
    {
        mst_seconds.detail().name_hash()[i] = seconds_hash.digest[i];
    }
    type_object->minimal().struct_type().member_seq().emplace_back(mst_seconds);

    MinimalStructMember mst_milliseconds;
    mst_milliseconds.common().member_id(memberId++);
    mst_milliseconds.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    mst_milliseconds.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    mst_milliseconds.common().member_flags().IS_EXTERNAL(false); // Unsupported
    mst_milliseconds.common().member_flags().IS_OPTIONAL(false);
    mst_milliseconds.common().member_flags().IS_MUST_UNDERSTAND(false);
    mst_milliseconds.common().member_flags().IS_KEY(false);
    mst_milliseconds.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    mst_milliseconds.common().member_type_id(*TypeObjectFactory::get_instance()->get_type_identifier("int32_t", false));


    MD5 milliseconds_hash("milliseconds");
    for (int i = 0; i < 4; ++i)
    {
        mst_milliseconds.detail().name_hash()[i] = milliseconds_hash.digest[i];
    }
    type_object->minimal().struct_type().member_seq().emplace_back(mst_milliseconds);


    // Header
    // TODO Inheritance
    //type_object->minimal().struct_type().header().base_type()._d(EK_MINIMAL);
    //type_object->minimal().struct_type().header().base_type().equivalence_hash()[0..13];
    TypeIdentifier identifier;
    identifier._d(EK_MINIMAL);

    eprosima::fastcdr::CdrSizeCalculator calculator(eprosima::fastcdr::CdrVersion::XCDRv1);
    size_t current_alignment {0};
    SerializedPayload_t payload(static_cast<uint32_t>(
                calculator.calculate_serialized_size(type_object->minimal().struct_type(), current_alignment) + 4));
    eprosima::fastcdr::FastBuffer fastbuffer((char*) payload.data, payload.max_size);
    // Fixed endian (Page 221, EquivalenceHash definition of Extensible and Dynamic Topic Types for DDS document)
    eprosima::fastcdr::Cdr ser(
        fastbuffer, eprosima::fastcdr::Cdr::LITTLE_ENDIANNESS,
        eprosima::fastcdr::CdrVersion::XCDRv1); // Object that serializes the data.
    payload.encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE;

    ser << *type_object;
#if FASTCDR_VERSION_MAJOR == 1
    payload.length = (uint32_t)ser.getSerializedDataLength(); //Get the serialized length
#else
    payload.length = (uint32_t)ser.get_serialized_data_length(); //Get the serialized length
#endif // FASTCDR_VERSION_MAJOR == 1
    MD5 objectHash;
    objectHash.update((char*)payload.data, payload.length);
    objectHash.finalize();
    for (int i = 0; i < 14; ++i)
    {
        identifier.equivalence_hash()[i] = objectHash.digest[i];
    }

    TypeObjectFactory::get_instance()->add_type_object("Timestamp", &identifier, type_object);
    delete type_object;
    return TypeObjectFactory::get_instance()->get_type_object("Timestamp", false);
}

const TypeObject* GetCompleteTimestampObject()
{
    const TypeObject* c_type_object = TypeObjectFactory::get_instance()->get_type_object("Timestamp", true);
    if (c_type_object != nullptr && c_type_object->_d() == EK_COMPLETE)
    {
        return c_type_object;
    }

    TypeObject* type_object = new TypeObject();
    type_object->_d(EK_COMPLETE);
    type_object->complete()._d(TK_STRUCTURE);

    type_object->complete().struct_type().struct_flags().IS_FINAL(false);
    type_object->complete().struct_type().struct_flags().IS_APPENDABLE(false);
    type_object->complete().struct_type().struct_flags().IS_MUTABLE(false);
    type_object->complete().struct_type().struct_flags().IS_NESTED(false);
    type_object->complete().struct_type().struct_flags().IS_AUTOID_HASH(false); // Unsupported

    MemberId memberId = 0;
    CompleteStructMember cst_seconds;
    cst_seconds.common().member_id(memberId++);
    cst_seconds.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    cst_seconds.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    cst_seconds.common().member_flags().IS_EXTERNAL(false); // Unsupported
    cst_seconds.common().member_flags().IS_OPTIONAL(false);
    cst_seconds.common().member_flags().IS_MUST_UNDERSTAND(false);
    cst_seconds.common().member_flags().IS_KEY(false);
    cst_seconds.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    cst_seconds.common().member_type_id(*TypeObjectFactory::get_instance()->get_type_identifier("int32_t", false));


    cst_seconds.detail().name("seconds");

    type_object->complete().struct_type().member_seq().emplace_back(cst_seconds);

    CompleteStructMember cst_milliseconds;
    cst_milliseconds.common().member_id(memberId++);
    cst_milliseconds.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    cst_milliseconds.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    cst_milliseconds.common().member_flags().IS_EXTERNAL(false); // Unsupported
    cst_milliseconds.common().member_flags().IS_OPTIONAL(false);
    cst_milliseconds.common().member_flags().IS_MUST_UNDERSTAND(false);
    cst_milliseconds.common().member_flags().IS_KEY(false);
    cst_milliseconds.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    cst_milliseconds.common().member_type_id(*TypeObjectFactory::get_instance()->get_type_identifier("int32_t", false));


    cst_milliseconds.detail().name("milliseconds");

    type_object->complete().struct_type().member_seq().emplace_back(cst_milliseconds);


    // Header
    type_object->complete().struct_type().header().detail().type_name("Timestamp");
    // TODO inheritance
    TypeIdentifier identifier;
    identifier._d(EK_COMPLETE);

    eprosima::fastcdr::CdrSizeCalculator calculator(eprosima::fastcdr::CdrVersion::XCDRv1);
    size_t current_alignment {0};
    SerializedPayload_t payload(static_cast<uint32_t>(
                calculator.calculate_serialized_size(type_object->complete().struct_type(), current_alignment) + 4));
    eprosima::fastcdr::FastBuffer fastbuffer((char*) payload.data, payload.max_size);
    // Fixed endian (Page 221, EquivalenceHash definition of Extensible and Dynamic Topic Types for DDS document)
    eprosima::fastcdr::Cdr ser(
        fastbuffer, eprosima::fastcdr::Cdr::LITTLE_ENDIANNESS,
        eprosima::fastcdr::CdrVersion::XCDRv1); // Object that serializes the data.
    payload.encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE;

    ser << *type_object;
#if FASTCDR_VERSION_MAJOR == 1
    payload.length = (uint32_t)ser.getSerializedDataLength(); //Get the serialized length
#else
    payload.length = (uint32_t)ser.get_serialized_data_length(); //Get the serialized length
#endif // FASTCDR_VERSION_MAJOR == 1
    MD5 objectHash;
    objectHash.update((char*)payload.data, payload.length);
    objectHash.finalize();
    for (int i = 0; i < 14; ++i)
    {
        identifier.equivalence_hash()[i] = objectHash.digest[i];
    }

    TypeObjectFactory::get_instance()->add_type_object("Timestamp", &identifier, type_object);
    delete type_object;
    return TypeObjectFactory::get_instance()->get_type_object("Timestamp", true);
}

const TypeIdentifier* GetPointIdentifier(
        bool complete)
{
    const TypeIdentifier* c_identifier = TypeObjectFactory::get_instance()->get_type_identifier("Point", complete);
    if (c_identifier != nullptr && (!complete || c_identifier->_d() == EK_COMPLETE))
    {
        return c_identifier;
    }

    GetPointObject(complete); // Generated inside
    return TypeObjectFactory::get_instance()->get_type_identifier("Point", complete);
}

const TypeObject* GetPointObject(
        bool complete)
{
    const TypeObject* c_type_object = TypeObjectFactory::get_instance()->get_type_object("Point", complete);
    if (c_type_object != nullptr)
    {
        return c_type_object;
    }
    else if (complete)
    {
        return GetCompletePointObject();
    }
    //else
    return GetMinimalPointObject();
}

const TypeObject* GetMinimalPointObject()
{
    const TypeObject* c_type_object = TypeObjectFactory::get_instance()->get_type_object("Point", false);
    if (c_type_object != nullptr)
    {
        return c_type_object;
    }

    TypeObject* type_object = new TypeObject();
    type_object->_d(EK_MINIMAL);
    type_object->minimal()._d(TK_STRUCTURE);

    type_object->minimal().struct_type().struct_flags().IS_FINAL(false);
    type_object->minimal().struct_type().struct_flags().IS_APPENDABLE(false);
    type_object->minimal().struct_type().struct_flags().IS_MUTABLE(false);
    type_object->minimal().struct_type().struct_flags().IS_NESTED(false);
    type_object->minimal().struct_type().struct_flags().IS_AUTOID_HASH(false); // Unsupported

    MemberId memberId = 0;
    MinimalStructMember mst_x;
    mst_x.common().member_id(memberId++);
    mst_x.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    mst_x.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    mst_x.common().member_flags().IS_EXTERNAL(false); // Unsupported
    mst_x.common().member_flags().IS_OPTIONAL(false);
    mst_x.common().member_flags().IS_MUST_UNDERSTAND(false);
    mst_x.common().member_flags().IS_KEY(false);
    mst_x.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    mst_x.common().member_type_id(*TypeObjectFactory::get_instance()->get_type_identifier("int32_t", false));


    MD5 x_hash("x");
    for (int i = 0; i < 4; ++i)
    {
        mst_x.detail().name_hash()[i] = x_hash.digest[i];
    }
    type_object->minimal().struct_type().member_seq().emplace_back(mst_x);

    MinimalStructMember mst_y;
    mst_y.common().member_id(memberId++);
    mst_y.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    mst_y.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    mst_y.common().member_flags().IS_EXTERNAL(false); // Unsupported
    mst_y.common().member_flags().IS_OPTIONAL(false);
    mst_y.common().member_flags().IS_MUST_UNDERSTAND(false);
    mst_y.common().member_flags().IS_KEY(false);
    mst_y.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    mst_y.common().member_type_id(*TypeObjectFactory::get_instance()->get_type_identifier("int32_t", false));


    MD5 y_hash("y");
    for (int i = 0; i < 4; ++i)
    {
        mst_y.detail().name_hash()[i] = y_hash.digest[i];
    }
    type_object->minimal().struct_type().member_seq().emplace_back(mst_y);

    MinimalStructMember mst_z;
    mst_z.common().member_id(memberId++);
    mst_z.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    mst_z.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    mst_z.common().member_flags().IS_EXTERNAL(false); // Unsupported
    mst_z.common().member_flags().IS_OPTIONAL(false);
    mst_z.common().member_flags().IS_MUST_UNDERSTAND(false);
    mst_z.common().member_flags().IS_KEY(false);
    mst_z.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    mst_z.common().member_type_id(*TypeObjectFactory::get_instance()->get_type_identifier("int32_t", false));


    MD5 z_hash("z");
    for (int i = 0; i < 4; ++i)
    {
        mst_z.detail().name_hash()[i] = z_hash.digest[i];
    }
    type_object->minimal().struct_type().member_seq().emplace_back(mst_z);


    // Header
    // TODO Inheritance
    //type_object->minimal().struct_type().header().base_type()._d(EK_MINIMAL);
    //type_object->minimal().struct_type().header().base_type().equivalence_hash()[0..13];
    TypeIdentifier identifier;
    identifier._d(EK_MINIMAL);

    eprosima::fastcdr::CdrSizeCalculator calculator(eprosima::fastcdr::CdrVersion::XCDRv1);
    size_t current_alignment {0};
    SerializedPayload_t payload(static_cast<uint32_t>(
                calculator.calculate_serialized_size(type_object->minimal().struct_type(), current_alignment) + 4));
    eprosima::fastcdr::FastBuffer fastbuffer((char*) payload.data, payload.max_size);
    // Fixed endian (Page 221, EquivalenceHash definition of Extensible and Dynamic Topic Types for DDS document)
    eprosima::fastcdr::Cdr ser(
        fastbuffer, eprosima::fastcdr::Cdr::LITTLE_ENDIANNESS,
        eprosima::fastcdr::CdrVersion::XCDRv1); // Object that serializes the data.
    payload.encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE;

    ser << *type_object;
#if FASTCDR_VERSION_MAJOR == 1
    payload.length = (uint32_t)ser.getSerializedDataLength(); //Get the serialized length
#else
    payload.length = (uint32_t)ser.get_serialized_data_length(); //Get the serialized length
#endif // FASTCDR_VERSION_MAJOR == 1
    MD5 objectHash;
    objectHash.update((char*)payload.data, payload.length);
    objectHash.finalize();
    for (int i = 0; i < 14; ++i)
    {
        identifier.equivalence_hash()[i] = objectHash.digest[i];
    }

    TypeObjectFactory::get_instance()->add_type_object("Point", &identifier, type_object);
    delete type_object;
    return TypeObjectFactory::get_instance()->get_type_object("Point", false);
}

const TypeObject* GetCompletePointObject()
{
    const TypeObject* c_type_object = TypeObjectFactory::get_instance()->get_type_object("Point", true);
    if (c_type_object != nullptr && c_type_object->_d() == EK_COMPLETE)
    {
        return c_type_object;
    }

    TypeObject* type_object = new TypeObject();
    type_object->_d(EK_COMPLETE);
    type_object->complete()._d(TK_STRUCTURE);

    type_object->complete().struct_type().struct_flags().IS_FINAL(false);
    type_object->complete().struct_type().struct_flags().IS_APPENDABLE(false);
    type_object->complete().struct_type().struct_flags().IS_MUTABLE(false);
    type_object->complete().struct_type().struct_flags().IS_NESTED(false);
    type_object->complete().struct_type().struct_flags().IS_AUTOID_HASH(false); // Unsupported

    MemberId memberId = 0;
    CompleteStructMember cst_x;
    cst_x.common().member_id(memberId++);
    cst_x.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    cst_x.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    cst_x.common().member_flags().IS_EXTERNAL(false); // Unsupported
    cst_x.common().member_flags().IS_OPTIONAL(false);
    cst_x.common().member_flags().IS_MUST_UNDERSTAND(false);
    cst_x.common().member_flags().IS_KEY(false);
    cst_x.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    cst_x.common().member_type_id(*TypeObjectFactory::get_instance()->get_type_identifier("int32_t", false));


    cst_x.detail().name("x");

    type_object->complete().struct_type().member_seq().emplace_back(cst_x);

    CompleteStructMember cst_y;
    cst_y.common().member_id(memberId++);
    cst_y.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    cst_y.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    cst_y.common().member_flags().IS_EXTERNAL(false); // Unsupported
    cst_y.common().member_flags().IS_OPTIONAL(false);
    cst_y.common().member_flags().IS_MUST_UNDERSTAND(false);
    cst_y.common().member_flags().IS_KEY(false);
    cst_y.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    cst_y.common().member_type_id(*TypeObjectFactory::get_instance()->get_type_identifier("int32_t", false));


    cst_y.detail().name("y");

    type_object->complete().struct_type().member_seq().emplace_back(cst_y);

    CompleteStructMember cst_z;
    cst_z.common().member_id(memberId++);
    cst_z.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    cst_z.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    cst_z.common().member_flags().IS_EXTERNAL(false); // Unsupported
    cst_z.common().member_flags().IS_OPTIONAL(false);
    cst_z.common().member_flags().IS_MUST_UNDERSTAND(false);
    cst_z.common().member_flags().IS_KEY(false);
    cst_z.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    cst_z.common().member_type_id(*TypeObjectFactory::get_instance()->get_type_identifier("int32_t", false));


    cst_z.detail().name("z");

    type_object->complete().struct_type().member_seq().emplace_back(cst_z);


    // Header
    type_object->complete().struct_type().header().detail().type_name("Point");
    // TODO inheritance
    TypeIdentifier identifier;
    identifier._d(EK_COMPLETE);

    eprosima::fastcdr::CdrSizeCalculator calculator(eprosima::fastcdr::CdrVersion::XCDRv1);
    size_t current_alignment {0};
    SerializedPayload_t payload(static_cast<uint32_t>(
                calculator.calculate_serialized_size(type_object->complete().struct_type(), current_alignment) + 4));
    eprosima::fastcdr::FastBuffer fastbuffer((char*) payload.data, payload.max_size);
    // Fixed endian (Page 221, EquivalenceHash definition of Extensible and Dynamic Topic Types for DDS document)
    eprosima::fastcdr::Cdr ser(
        fastbuffer, eprosima::fastcdr::Cdr::LITTLE_ENDIANNESS,
        eprosima::fastcdr::CdrVersion::XCDRv1); // Object that serializes the data.
    payload.encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE;

    ser << *type_object;
#if FASTCDR_VERSION_MAJOR == 1
    payload.length = (uint32_t)ser.getSerializedDataLength(); //Get the serialized length
#else
    payload.length = (uint32_t)ser.get_serialized_data_length(); //Get the serialized length
#endif // FASTCDR_VERSION_MAJOR == 1
    MD5 objectHash;
    objectHash.update((char*)payload.data, payload.length);
    objectHash.finalize();
    for (int i = 0; i < 14; ++i)
    {
        identifier.equivalence_hash()[i] = objectHash.digest[i];
    }

    TypeObjectFactory::get_instance()->add_type_object("Point", &identifier, type_object);
    delete type_object;
    return TypeObjectFactory::get_instance()->get_type_object("Point", true);
}

const TypeIdentifier* GetMessageDescriptorIdentifier(
        bool complete)
{
    const TypeIdentifier* c_identifier = TypeObjectFactory::get_instance()->get_type_identifier("MessageDescriptor",
                    complete);
    if (c_identifier != nullptr && (!complete || c_identifier->_d() == EK_COMPLETE))
    {
        return c_identifier;
    }

    GetMessageDescriptorObject(complete); // Generated inside
    return TypeObjectFactory::get_instance()->get_type_identifier("MessageDescriptor", complete);
}

const TypeObject* GetMessageDescriptorObject(
        bool complete)
{
    const TypeObject* c_type_object = TypeObjectFactory::get_instance()->get_type_object("MessageDescriptor", complete);
    if (c_type_object != nullptr)
    {
        return c_type_object;
    }
    else if (complete)
    {
        return GetCompleteMessageDescriptorObject();
    }
    //else
    return GetMinimalMessageDescriptorObject();
}

const TypeObject* GetMinimalMessageDescriptorObject()
{
    const TypeObject* c_type_object = TypeObjectFactory::get_instance()->get_type_object("MessageDescriptor", false);
    if (c_type_object != nullptr)
    {
        return c_type_object;
    }

    TypeObject* type_object = new TypeObject();
    type_object->_d(EK_MINIMAL);
    type_object->minimal()._d(TK_STRUCTURE);

    type_object->minimal().struct_type().struct_flags().IS_FINAL(false);
    type_object->minimal().struct_type().struct_flags().IS_APPENDABLE(false);
    type_object->minimal().struct_type().struct_flags().IS_MUTABLE(false);
    type_object->minimal().struct_type().struct_flags().IS_NESTED(false);
    type_object->minimal().struct_type().struct_flags().IS_AUTOID_HASH(false); // Unsupported

    MemberId memberId = 0;
    MinimalStructMember mst_id;
    mst_id.common().member_id(memberId++);
    mst_id.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    mst_id.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    mst_id.common().member_flags().IS_EXTERNAL(false); // Unsupported
    mst_id.common().member_flags().IS_OPTIONAL(false);
    mst_id.common().member_flags().IS_MUST_UNDERSTAND(false);
    mst_id.common().member_flags().IS_KEY(false);
    mst_id.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    mst_id.common().member_type_id(*TypeObjectFactory::get_instance()->get_type_identifier("uint32_t", false));


    MD5 id_hash("id");
    for (int i = 0; i < 4; ++i)
    {
        mst_id.detail().name_hash()[i] = id_hash.digest[i];
    }
    type_object->minimal().struct_type().member_seq().emplace_back(mst_id);

    MinimalStructMember mst_topic;
    mst_topic.common().member_id(memberId++);
    mst_topic.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    mst_topic.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    mst_topic.common().member_flags().IS_EXTERNAL(false); // Unsupported
    mst_topic.common().member_flags().IS_OPTIONAL(false);
    mst_topic.common().member_flags().IS_MUST_UNDERSTAND(false);
    mst_topic.common().member_flags().IS_KEY(false);
    mst_topic.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    mst_topic.common().member_type_id(*TypeObjectFactory::get_instance()->get_string_identifier(255, false));

    MD5 topic_hash("topic");
    for (int i = 0; i < 4; ++i)
    {
        mst_topic.detail().name_hash()[i] = topic_hash.digest[i];
    }
    type_object->minimal().struct_type().member_seq().emplace_back(mst_topic);

    MinimalStructMember mst_time;
    mst_time.common().member_id(memberId++);
    mst_time.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    mst_time.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    mst_time.common().member_flags().IS_EXTERNAL(false); // Unsupported
    mst_time.common().member_flags().IS_OPTIONAL(false);
    mst_time.common().member_flags().IS_MUST_UNDERSTAND(false);
    mst_time.common().member_flags().IS_KEY(false);
    mst_time.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    mst_time.common().member_type_id(*GetTimestampIdentifier(false));

    MD5 time_hash("time");
    for (int i = 0; i < 4; ++i)
    {
        mst_time.detail().name_hash()[i] = time_hash.digest[i];
    }
    type_object->minimal().struct_type().member_seq().emplace_back(mst_time);


    // Header
    // TODO Inheritance
    //type_object->minimal().struct_type().header().base_type()._d(EK_MINIMAL);
    //type_object->minimal().struct_type().header().base_type().equivalence_hash()[0..13];
    TypeIdentifier identifier;
    identifier._d(EK_MINIMAL);

    eprosima::fastcdr::CdrSizeCalculator calculator(eprosima::fastcdr::CdrVersion::XCDRv1);
    size_t current_alignment {0};
    SerializedPayload_t payload(static_cast<uint32_t>(
                calculator.calculate_serialized_size(type_object->minimal().struct_type(), current_alignment) + 4));
    eprosima::fastcdr::FastBuffer fastbuffer((char*) payload.data, payload.max_size);
    // Fixed endian (Page 221, EquivalenceHash definition of Extensible and Dynamic Topic Types for DDS document)
    eprosima::fastcdr::Cdr ser(
        fastbuffer, eprosima::fastcdr::Cdr::LITTLE_ENDIANNESS,
        eprosima::fastcdr::CdrVersion::XCDRv1); // Object that serializes the data.
    payload.encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE;

    ser << *type_object;
#if FASTCDR_VERSION_MAJOR == 1
    payload.length = (uint32_t)ser.getSerializedDataLength(); //Get the serialized length
#else
    payload.length = (uint32_t)ser.get_serialized_data_length(); //Get the serialized length
#endif // FASTCDR_VERSION_MAJOR == 1
    MD5 objectHash;
    objectHash.update((char*)payload.data, payload.length);
    objectHash.finalize();
    for (int i = 0; i < 14; ++i)
    {
        identifier.equivalence_hash()[i] = objectHash.digest[i];
    }

    TypeObjectFactory::get_instance()->add_type_object("MessageDescriptor", &identifier, type_object);
    delete type_object;
    return TypeObjectFactory::get_instance()->get_type_object("MessageDescriptor", false);
}

const TypeObject* GetCompleteMessageDescriptorObject()
{
    const TypeObject* c_type_object = TypeObjectFactory::get_instance()->get_type_object("MessageDescriptor", true);
    if (c_type_object != nullptr && c_type_object->_d() == EK_COMPLETE)
    {
        return c_type_object;
    }

    TypeObject* type_object = new TypeObject();
    type_object->_d(EK_COMPLETE);
    type_object->complete()._d(TK_STRUCTURE);

    type_object->complete().struct_type().struct_flags().IS_FINAL(false);
    type_object->complete().struct_type().struct_flags().IS_APPENDABLE(false);
    type_object->complete().struct_type().struct_flags().IS_MUTABLE(false);
    type_object->complete().struct_type().struct_flags().IS_NESTED(false);
    type_object->complete().struct_type().struct_flags().IS_AUTOID_HASH(false); // Unsupported

    MemberId memberId = 0;
    CompleteStructMember cst_id;
    cst_id.common().member_id(memberId++);
    cst_id.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    cst_id.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    cst_id.common().member_flags().IS_EXTERNAL(false); // Unsupported
    cst_id.common().member_flags().IS_OPTIONAL(false);
    cst_id.common().member_flags().IS_MUST_UNDERSTAND(false);
    cst_id.common().member_flags().IS_KEY(false);
    cst_id.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    cst_id.common().member_type_id(*TypeObjectFactory::get_instance()->get_type_identifier("uint32_t", false));


    cst_id.detail().name("id");

    type_object->complete().struct_type().member_seq().emplace_back(cst_id);

    CompleteStructMember cst_topic;
    cst_topic.common().member_id(memberId++);
    cst_topic.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    cst_topic.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    cst_topic.common().member_flags().IS_EXTERNAL(false); // Unsupported
    cst_topic.common().member_flags().IS_OPTIONAL(false);
    cst_topic.common().member_flags().IS_MUST_UNDERSTAND(false);
    cst_topic.common().member_flags().IS_KEY(false);
    cst_topic.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    cst_topic.common().member_type_id(*TypeObjectFactory::get_instance()->get_string_identifier(255, false));

    cst_topic.detail().name("topic");

    type_object->complete().struct_type().member_seq().emplace_back(cst_topic);

    CompleteStructMember cst_time;
    cst_time.common().member_id(memberId++);
    cst_time.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    cst_time.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    cst_time.common().member_flags().IS_EXTERNAL(false); // Unsupported
    cst_time.common().member_flags().IS_OPTIONAL(false);
    cst_time.common().member_flags().IS_MUST_UNDERSTAND(false);
    cst_time.common().member_flags().IS_KEY(false);
    cst_time.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    cst_time.common().member_type_id(*GetTimestampIdentifier(true));

    cst_time.detail().name("time");

    type_object->complete().struct_type().member_seq().emplace_back(cst_time);


    // Header
    type_object->complete().struct_type().header().detail().type_name("MessageDescriptor");
    // TODO inheritance
    TypeIdentifier identifier;
    identifier._d(EK_COMPLETE);

    eprosima::fastcdr::CdrSizeCalculator calculator(eprosima::fastcdr::CdrVersion::XCDRv1);
    size_t current_alignment {0};
    SerializedPayload_t payload(static_cast<uint32_t>(
                calculator.calculate_serialized_size(type_object->complete().struct_type(), current_alignment) + 4));
    eprosima::fastcdr::FastBuffer fastbuffer((char*) payload.data, payload.max_size);
    // Fixed endian (Page 221, EquivalenceHash definition of Extensible and Dynamic Topic Types for DDS document)
    eprosima::fastcdr::Cdr ser(
        fastbuffer, eprosima::fastcdr::Cdr::LITTLE_ENDIANNESS,
        eprosima::fastcdr::CdrVersion::XCDRv1); // Object that serializes the data.
    payload.encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE;

    ser << *type_object;
#if FASTCDR_VERSION_MAJOR == 1
    payload.length = (uint32_t)ser.getSerializedDataLength(); //Get the serialized length
#else
    payload.length = (uint32_t)ser.get_serialized_data_length(); //Get the serialized length
#endif // FASTCDR_VERSION_MAJOR == 1
    MD5 objectHash;
    objectHash.update((char*)payload.data, payload.length);
    objectHash.finalize();
    for (int i = 0; i < 14; ++i)
    {
        identifier.equivalence_hash()[i] = objectHash.digest[i];
    }

    TypeObjectFactory::get_instance()->add_type_object("MessageDescriptor", &identifier, type_object);
    delete type_object;
    return TypeObjectFactory::get_instance()->get_type_object("MessageDescriptor", true);
}

const TypeIdentifier* GetMessageIdentifier(
        bool complete)
{
    const TypeIdentifier* c_identifier = TypeObjectFactory::get_instance()->get_type_identifier("Message", complete);
    if (c_identifier != nullptr && (!complete || c_identifier->_d() == EK_COMPLETE))
    {
        return c_identifier;
    }

    GetMessageObject(complete); // Generated inside
    return TypeObjectFactory::get_instance()->get_type_identifier("Message", complete);
}

const TypeObject* GetMessageObject(
        bool complete)
{
    const TypeObject* c_type_object = TypeObjectFactory::get_instance()->get_type_object("Message", complete);
    if (c_type_object != nullptr)
    {
        return c_type_object;
    }
    else if (complete)
    {
        return GetCompleteMessageObject();
    }
    //else
    return GetMinimalMessageObject();
}

const TypeObject* GetMinimalMessageObject()
{
    const TypeObject* c_type_object = TypeObjectFactory::get_instance()->get_type_object("Message", false);
    if (c_type_object != nullptr)
    {
        return c_type_object;
    }

    TypeObject* type_object = new TypeObject();
    type_object->_d(EK_MINIMAL);
    type_object->minimal()._d(TK_STRUCTURE);

    type_object->minimal().struct_type().struct_flags().IS_FINAL(false);
    type_object->minimal().struct_type().struct_flags().IS_APPENDABLE(false);
    type_object->minimal().struct_type().struct_flags().IS_MUTABLE(false);
    type_object->minimal().struct_type().struct_flags().IS_NESTED(false);
    type_object->minimal().struct_type().struct_flags().IS_AUTOID_HASH(false); // Unsupported

    MemberId memberId = 0;
    MinimalStructMember mst_descriptor;
    mst_descriptor.common().member_id(memberId++);
    mst_descriptor.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    mst_descriptor.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    mst_descriptor.common().member_flags().IS_EXTERNAL(false); // Unsupported
    mst_descriptor.common().member_flags().IS_OPTIONAL(false);
    mst_descriptor.common().member_flags().IS_MUST_UNDERSTAND(false);
    mst_descriptor.common().member_flags().IS_KEY(false);
    mst_descriptor.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    mst_descriptor.common().member_type_id(*GetMessageDescriptorIdentifier(false));

    MD5 descriptor_hash("descriptor");
    for (int i = 0; i < 4; ++i)
    {
        mst_descriptor.detail().name_hash()[i] = descriptor_hash.digest[i];
    }
    type_object->minimal().struct_type().member_seq().emplace_back(mst_descriptor);

    MinimalStructMember mst_message;
    mst_message.common().member_id(memberId++);
    mst_message.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    mst_message.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    mst_message.common().member_flags().IS_EXTERNAL(false); // Unsupported
    mst_message.common().member_flags().IS_OPTIONAL(false);
    mst_message.common().member_flags().IS_MUST_UNDERSTAND(false);
    mst_message.common().member_flags().IS_KEY(false);
    mst_message.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    mst_message.common().member_type_id(*TypeObjectFactory::get_instance()->get_string_identifier(255, false));

    MD5 message_hash("message");
    for (int i = 0; i < 4; ++i)
    {
        mst_message.detail().name_hash()[i] = message_hash.digest[i];
    }
    type_object->minimal().struct_type().member_seq().emplace_back(mst_message);


    // Header
    // TODO Inheritance
    //type_object->minimal().struct_type().header().base_type()._d(EK_MINIMAL);
    //type_object->minimal().struct_type().header().base_type().equivalence_hash()[0..13];
    TypeIdentifier identifier;
    identifier._d(EK_MINIMAL);

    eprosima::fastcdr::CdrSizeCalculator calculator(eprosima::fastcdr::CdrVersion::XCDRv1);
    size_t current_alignment {0};
    SerializedPayload_t payload(static_cast<uint32_t>(
                calculator.calculate_serialized_size(type_object->minimal().struct_type(), current_alignment) + 4));
    eprosima::fastcdr::FastBuffer fastbuffer((char*) payload.data, payload.max_size);
    // Fixed endian (Page 221, EquivalenceHash definition of Extensible and Dynamic Topic Types for DDS document)
    eprosima::fastcdr::Cdr ser(
        fastbuffer, eprosima::fastcdr::Cdr::LITTLE_ENDIANNESS,
        eprosima::fastcdr::CdrVersion::XCDRv1); // Object that serializes the data.
    payload.encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE;

    ser << *type_object;
#if FASTCDR_VERSION_MAJOR == 1
    payload.length = (uint32_t)ser.getSerializedDataLength(); //Get the serialized length
#else
    payload.length = (uint32_t)ser.get_serialized_data_length(); //Get the serialized length
#endif // FASTCDR_VERSION_MAJOR == 1
    MD5 objectHash;
    objectHash.update((char*)payload.data, payload.length);
    objectHash.finalize();
    for (int i = 0; i < 14; ++i)
    {
        identifier.equivalence_hash()[i] = objectHash.digest[i];
    }

    TypeObjectFactory::get_instance()->add_type_object("Message", &identifier, type_object);
    delete type_object;
    return TypeObjectFactory::get_instance()->get_type_object("Message", false);
}

const TypeObject* GetCompleteMessageObject()
{
    const TypeObject* c_type_object = TypeObjectFactory::get_instance()->get_type_object("Message", true);
    if (c_type_object != nullptr && c_type_object->_d() == EK_COMPLETE)
    {
        return c_type_object;
    }

    TypeObject* type_object = new TypeObject();
    type_object->_d(EK_COMPLETE);
    type_object->complete()._d(TK_STRUCTURE);

    type_object->complete().struct_type().struct_flags().IS_FINAL(false);
    type_object->complete().struct_type().struct_flags().IS_APPENDABLE(false);
    type_object->complete().struct_type().struct_flags().IS_MUTABLE(false);
    type_object->complete().struct_type().struct_flags().IS_NESTED(false);
    type_object->complete().struct_type().struct_flags().IS_AUTOID_HASH(false); // Unsupported

    MemberId memberId = 0;
    CompleteStructMember cst_descriptor;
    cst_descriptor.common().member_id(memberId++);
    cst_descriptor.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    cst_descriptor.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    cst_descriptor.common().member_flags().IS_EXTERNAL(false); // Unsupported
    cst_descriptor.common().member_flags().IS_OPTIONAL(false);
    cst_descriptor.common().member_flags().IS_MUST_UNDERSTAND(false);
    cst_descriptor.common().member_flags().IS_KEY(false);
    cst_descriptor.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    cst_descriptor.common().member_type_id(*GetMessageDescriptorIdentifier(true));

    cst_descriptor.detail().name("descriptor");

    type_object->complete().struct_type().member_seq().emplace_back(cst_descriptor);

    CompleteStructMember cst_message;
    cst_message.common().member_id(memberId++);
    cst_message.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    cst_message.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    cst_message.common().member_flags().IS_EXTERNAL(false); // Unsupported
    cst_message.common().member_flags().IS_OPTIONAL(false);
    cst_message.common().member_flags().IS_MUST_UNDERSTAND(false);
    cst_message.common().member_flags().IS_KEY(false);
    cst_message.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    cst_message.common().member_type_id(*TypeObjectFactory::get_instance()->get_string_identifier(255, false));

    cst_message.detail().name("message");

    type_object->complete().struct_type().member_seq().emplace_back(cst_message);


    // Header
    type_object->complete().struct_type().header().detail().type_name("Message");
    // TODO inheritance
    TypeIdentifier identifier;
    identifier._d(EK_COMPLETE);

    eprosima::fastcdr::CdrSizeCalculator calculator(eprosima::fastcdr::CdrVersion::XCDRv1);
    size_t current_alignment {0};
    SerializedPayload_t payload(static_cast<uint32_t>(
                calculator.calculate_serialized_size(type_object->complete().struct_type(), current_alignment) + 4));
    eprosima::fastcdr::FastBuffer fastbuffer((char*) payload.data, payload.max_size);
    // Fixed endian (Page 221, EquivalenceHash definition of Extensible and Dynamic Topic Types for DDS document)
    eprosima::fastcdr::Cdr ser(
        fastbuffer, eprosima::fastcdr::Cdr::LITTLE_ENDIANNESS,
        eprosima::fastcdr::CdrVersion::XCDRv1); // Object that serializes the data.
    payload.encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE;

    ser << *type_object;
#if FASTCDR_VERSION_MAJOR == 1
    payload.length = (uint32_t)ser.getSerializedDataLength(); //Get the serialized length
#else
    payload.length = (uint32_t)ser.get_serialized_data_length(); //Get the serialized length
#endif // FASTCDR_VERSION_MAJOR == 1
    MD5 objectHash;
    objectHash.update((char*)payload.data, payload.length);
    objectHash.finalize();
    for (int i = 0; i < 14; ++i)
    {
        identifier.equivalence_hash()[i] = objectHash.digest[i];
    }

    TypeObjectFactory::get_instance()->add_type_object("Message", &identifier, type_object);
    delete type_object;
    return TypeObjectFactory::get_instance()->get_type_object("Message", true);
}

const TypeIdentifier* GetCompleteDataIdentifier(
        bool complete)
{
    const TypeIdentifier* c_identifier =
            TypeObjectFactory::get_instance()->get_type_identifier("CompleteData", complete);
    if (c_identifier != nullptr && (!complete || c_identifier->_d() == EK_COMPLETE))
    {
        return c_identifier;
    }

    GetCompleteDataObject(complete); // Generated inside
    return TypeObjectFactory::get_instance()->get_type_identifier("CompleteData", complete);
}

const TypeObject* GetCompleteDataObject(
        bool complete)
{
    const TypeObject* c_type_object = TypeObjectFactory::get_instance()->get_type_object("CompleteData", complete);
    if (c_type_object != nullptr)
    {
        return c_type_object;
    }
    else if (complete)
    {
        return GetCompleteCompleteDataObject();
    }
    //else
    return GetMinimalCompleteDataObject();
}

const TypeObject* GetMinimalCompleteDataObject()
{
    const TypeObject* c_type_object = TypeObjectFactory::get_instance()->get_type_object("CompleteData", false);
    if (c_type_object != nullptr)
    {
        return c_type_object;
    }

    TypeObject* type_object = new TypeObject();
    type_object->_d(EK_MINIMAL);
    type_object->minimal()._d(TK_STRUCTURE);

    type_object->minimal().struct_type().struct_flags().IS_FINAL(false);
    type_object->minimal().struct_type().struct_flags().IS_APPENDABLE(false);
    type_object->minimal().struct_type().struct_flags().IS_MUTABLE(false);
    type_object->minimal().struct_type().struct_flags().IS_NESTED(false);
    type_object->minimal().struct_type().struct_flags().IS_AUTOID_HASH(false); // Unsupported

    MemberId memberId = 0;
    MinimalStructMember mst_index;
    mst_index.common().member_id(memberId++);
    mst_index.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    mst_index.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    mst_index.common().member_flags().IS_EXTERNAL(false); // Unsupported
    mst_index.common().member_flags().IS_OPTIONAL(false);
    mst_index.common().member_flags().IS_MUST_UNDERSTAND(false);
    mst_index.common().member_flags().IS_KEY(false);
    mst_index.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    mst_index.common().member_type_id(*TypeObjectFactory::get_instance()->get_type_identifier("uint32_t", false));


    MD5 index_hash("index");
    for (int i = 0; i < 4; ++i)
    {
        mst_index.detail().name_hash()[i] = index_hash.digest[i];
    }
    type_object->minimal().struct_type().member_seq().emplace_back(mst_index);

    MinimalStructMember mst_main_point;
    mst_main_point.common().member_id(memberId++);
    mst_main_point.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    mst_main_point.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    mst_main_point.common().member_flags().IS_EXTERNAL(false); // Unsupported
    mst_main_point.common().member_flags().IS_OPTIONAL(false);
    mst_main_point.common().member_flags().IS_MUST_UNDERSTAND(false);
    mst_main_point.common().member_flags().IS_KEY(false);
    mst_main_point.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    mst_main_point.common().member_type_id(*GetPointIdentifier(false));

    MD5 main_point_hash("main_point");
    for (int i = 0; i < 4; ++i)
    {
        mst_main_point.detail().name_hash()[i] = main_point_hash.digest[i];
    }
    type_object->minimal().struct_type().member_seq().emplace_back(mst_main_point);

    MinimalStructMember mst_internal_data;
    mst_internal_data.common().member_id(memberId++);
    mst_internal_data.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    mst_internal_data.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    mst_internal_data.common().member_flags().IS_EXTERNAL(false); // Unsupported
    mst_internal_data.common().member_flags().IS_OPTIONAL(false);
    mst_internal_data.common().member_flags().IS_MUST_UNDERSTAND(false);
    mst_internal_data.common().member_flags().IS_KEY(false);
    mst_internal_data.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    mst_internal_data.common().member_type_id(*TypeObjectFactory::get_instance()->get_sequence_identifier("Point", 100,
            false));

    MD5 internal_data_hash("internal_data");
    for (int i = 0; i < 4; ++i)
    {
        mst_internal_data.detail().name_hash()[i] = internal_data_hash.digest[i];
    }
    type_object->minimal().struct_type().member_seq().emplace_back(mst_internal_data);

    MinimalStructMember mst_messages;
    mst_messages.common().member_id(memberId++);
    mst_messages.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    mst_messages.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    mst_messages.common().member_flags().IS_EXTERNAL(false); // Unsupported
    mst_messages.common().member_flags().IS_OPTIONAL(false);
    mst_messages.common().member_flags().IS_MUST_UNDERSTAND(false);
    mst_messages.common().member_flags().IS_KEY(false);
    mst_messages.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    mst_messages.common().member_type_id(*TypeObjectFactory::get_instance()->get_array_identifier("Message", {2},
            false));

    MD5 messages_hash("messages");
    for (int i = 0; i < 4; ++i)
    {
        mst_messages.detail().name_hash()[i] = messages_hash.digest[i];
    }
    type_object->minimal().struct_type().member_seq().emplace_back(mst_messages);


    // Header
    // TODO Inheritance
    //type_object->minimal().struct_type().header().base_type()._d(EK_MINIMAL);
    //type_object->minimal().struct_type().header().base_type().equivalence_hash()[0..13];
    TypeIdentifier identifier;
    identifier._d(EK_MINIMAL);

    eprosima::fastcdr::CdrSizeCalculator calculator(eprosima::fastcdr::CdrVersion::XCDRv1);
    size_t current_alignment {0};
    SerializedPayload_t payload(static_cast<uint32_t>(
                calculator.calculate_serialized_size(type_object->minimal().struct_type(), current_alignment) + 4));
    eprosima::fastcdr::FastBuffer fastbuffer((char*) payload.data, payload.max_size);
    // Fixed endian (Page 221, EquivalenceHash definition of Extensible and Dynamic Topic Types for DDS document)
    eprosima::fastcdr::Cdr ser(
        fastbuffer, eprosima::fastcdr::Cdr::LITTLE_ENDIANNESS,
        eprosima::fastcdr::CdrVersion::XCDRv1); // Object that serializes the data.
    payload.encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE;

    ser << *type_object;
#if FASTCDR_VERSION_MAJOR == 1
    payload.length = (uint32_t)ser.getSerializedDataLength(); //Get the serialized length
#else
    payload.length = (uint32_t)ser.get_serialized_data_length(); //Get the serialized length
#endif // FASTCDR_VERSION_MAJOR == 1
    MD5 objectHash;
    objectHash.update((char*)payload.data, payload.length);
    objectHash.finalize();
    for (int i = 0; i < 14; ++i)
    {
        identifier.equivalence_hash()[i] = objectHash.digest[i];
    }

    TypeObjectFactory::get_instance()->add_type_object("CompleteData", &identifier, type_object);
    delete type_object;
    return TypeObjectFactory::get_instance()->get_type_object("CompleteData", false);
}

const TypeObject* GetCompleteCompleteDataObject()
{
    const TypeObject* c_type_object = TypeObjectFactory::get_instance()->get_type_object("CompleteData", true);
    if (c_type_object != nullptr && c_type_object->_d() == EK_COMPLETE)
    {
        return c_type_object;
    }

    TypeObject* type_object = new TypeObject();
    type_object->_d(EK_COMPLETE);
    type_object->complete()._d(TK_STRUCTURE);

    type_object->complete().struct_type().struct_flags().IS_FINAL(false);
    type_object->complete().struct_type().struct_flags().IS_APPENDABLE(false);
    type_object->complete().struct_type().struct_flags().IS_MUTABLE(false);
    type_object->complete().struct_type().struct_flags().IS_NESTED(false);
    type_object->complete().struct_type().struct_flags().IS_AUTOID_HASH(false); // Unsupported

    MemberId memberId = 0;
    CompleteStructMember cst_index;
    cst_index.common().member_id(memberId++);
    cst_index.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    cst_index.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    cst_index.common().member_flags().IS_EXTERNAL(false); // Unsupported
    cst_index.common().member_flags().IS_OPTIONAL(false);
    cst_index.common().member_flags().IS_MUST_UNDERSTAND(false);
    cst_index.common().member_flags().IS_KEY(false);
    cst_index.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    cst_index.common().member_type_id(*TypeObjectFactory::get_instance()->get_type_identifier("uint32_t", false));


    cst_index.detail().name("index");

    type_object->complete().struct_type().member_seq().emplace_back(cst_index);

    CompleteStructMember cst_main_point;
    cst_main_point.common().member_id(memberId++);
    cst_main_point.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    cst_main_point.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    cst_main_point.common().member_flags().IS_EXTERNAL(false); // Unsupported
    cst_main_point.common().member_flags().IS_OPTIONAL(false);
    cst_main_point.common().member_flags().IS_MUST_UNDERSTAND(false);
    cst_main_point.common().member_flags().IS_KEY(false);
    cst_main_point.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    cst_main_point.common().member_type_id(*GetPointIdentifier(true));

    cst_main_point.detail().name("main_point");

    type_object->complete().struct_type().member_seq().emplace_back(cst_main_point);

    CompleteStructMember cst_internal_data;
    cst_internal_data.common().member_id(memberId++);
    cst_internal_data.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    cst_internal_data.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    cst_internal_data.common().member_flags().IS_EXTERNAL(false); // Unsupported
    cst_internal_data.common().member_flags().IS_OPTIONAL(false);
    cst_internal_data.common().member_flags().IS_MUST_UNDERSTAND(false);
    cst_internal_data.common().member_flags().IS_KEY(false);
    cst_internal_data.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    cst_internal_data.common().member_type_id(*TypeObjectFactory::get_instance()->get_sequence_identifier("Point", 100,
            true));

    cst_internal_data.detail().name("internal_data");

    type_object->complete().struct_type().member_seq().emplace_back(cst_internal_data);

    CompleteStructMember cst_messages;
    cst_messages.common().member_id(memberId++);
    cst_messages.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported
    cst_messages.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported
    cst_messages.common().member_flags().IS_EXTERNAL(false); // Unsupported
    cst_messages.common().member_flags().IS_OPTIONAL(false);
    cst_messages.common().member_flags().IS_MUST_UNDERSTAND(false);
    cst_messages.common().member_flags().IS_KEY(false);
    cst_messages.common().member_flags().IS_DEFAULT(false); // Doesn't apply
    cst_messages.common().member_type_id(*TypeObjectFactory::get_instance()->get_array_identifier("Message", {2},
            true));

    cst_messages.detail().name("messages");

    type_object->complete().struct_type().member_seq().emplace_back(cst_messages);


    // Header
    type_object->complete().struct_type().header().detail().type_name("CompleteData");
    // TODO inheritance
    TypeIdentifier identifier;
    identifier._d(EK_COMPLETE);

    eprosima::fastcdr::CdrSizeCalculator calculator(eprosima::fastcdr::CdrVersion::XCDRv1);
    size_t current_alignment {0};
    SerializedPayload_t payload(static_cast<uint32_t>(
                calculator.calculate_serialized_size(type_object->complete().struct_type(), current_alignment) + 4));
    eprosima::fastcdr::FastBuffer fastbuffer((char*) payload.data, payload.max_size);
    // Fixed endian (Page 221, EquivalenceHash definition of Extensible and Dynamic Topic Types for DDS document)
    eprosima::fastcdr::Cdr ser(
        fastbuffer, eprosima::fastcdr::Cdr::LITTLE_ENDIANNESS,
        eprosima::fastcdr::CdrVersion::XCDRv1); // Object that serializes the data.
    payload.encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE;

    ser << *type_object;
#if FASTCDR_VERSION_MAJOR == 1
    payload.length = (uint32_t)ser.getSerializedDataLength(); //Get the serialized length
#else
    payload.length = (uint32_t)ser.get_serialized_data_length(); //Get the serialized length
#endif // FASTCDR_VERSION_MAJOR == 1
    MD5 objectHash;
    objectHash.update((char*)payload.data, payload.length);
    objectHash.finalize();
    for (int i = 0; i < 14; ++i)
    {
        identifier.equivalence_hash()[i] = objectHash.digest[i];
    }

    TypeObjectFactory::get_instance()->add_type_object("CompleteData", &identifier, type_object);
    delete type_object;
    return TypeObjectFactory::get_instance()->get_type_object("CompleteData", true);
}
